package com.glsc.ngateway.platform.service.other;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.glsc.ngateway.common.api.common.ex.GatewayException;
import com.glsc.ngateway.common.api.common.utils.CommonUtils;
import com.glsc.ngateway.common.api.common.utils.PageUtil;
import com.glsc.ngateway.common.api.ldap.dto.LdapEhrDeptDto;
import com.glsc.ngateway.common.api.ldap.dto.LdapEhrDeptSearchDto;
import com.glsc.ngateway.common.api.ldap.dto.LdapEhrEmpDto;
import com.glsc.ngateway.common.api.ldap.dto.LdapEhrEmpSearchDto;
import com.glsc.ngateway.common.api.ldap.feign.IFeignLdapService;
import com.glsc.ngateway.common.api.ldap.resp.LdapResponse;
import com.glsc.ngateway.common.api.platform.dto.other.FortressAccountImportDto;
import com.glsc.ngateway.platform.dto.FortressNewMachineImportDto;
import com.glsc.ngateway.common.api.platform.dto.user.PlatformUserDto;
import com.glsc.ngateway.common.base.domain.mysql.gateway.other.Fortress;
import com.glsc.ngateway.platform.domain.FortressNew;
import com.glsc.ngateway.common.base.domain.mysql.gateway.other.IpSystemCode;
import com.glsc.ngateway.common.base.domain.mysql.gateway.other.SystemLicenseExpire;
import com.glsc.ngateway.common.base.domain.mysql.gateway.system.SystemMain;
import com.glsc.ngateway.platform.vo.converter.FortressNewMachineMapper;
import com.glsc.ngateway.common.base.enums.OaHrmresourceStatusEnum;
import com.glsc.ngateway.common.base.repo.mysql.gateway.other.SystemLicenseExpireRepository;
import com.glsc.ngateway.platform.repo.FortressNewRepository;
import com.glsc.ngateway.platform.service.MailService;
import com.glsc.ngateway.platform.service.system.SystemMainService;
import com.glsc.ngateway.platform.utils.AssertOverride;
import com.glsc.ngateway.platform.utils.SpecificationUtil;
import com.glsc.ngateway.platform.utils.report.ReportFileConfigEnum;
import com.glsc.ngateway.platform.utils.report.ReportFileUtil;
import com.glsc.ngateway.platform.utils.report.ReportUploadContext;
import lombok.SneakyThrows;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.io.IOException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class FortressNewService {

    private static final Logger logger = LoggerFactory.getLogger(FortressNewService.class);

    @Resource
    private SystemLicenseExpireRepository systemLicenseExpireRepository;

    @Resource
    private MailService mailService;
    @Resource
    private IFeignLdapService iFeignLdapService;
    @Resource
    private SystemMainService systemMainService;
    @Resource
    private FortressNewRepository fortressNewRepository;

    @PersistenceContext
    @Qualifier("entityManagerMysql")
    private EntityManager entityManager;

    public SystemLicenseExpire save(SystemLicenseExpire systemLicense) {
        if(StringUtils.isEmpty(systemLicense.getSystemName())){
            throw GatewayException.error("系统名称不能为空");
        }
        systemLicense.setSystemName(StringUtils.trim(systemLicense.getSystemName()));

        //校验管理员邮箱合法性
        if(StringUtils.isNotEmpty(systemLicense.getAdminEmail())){
            String emailStr=systemLicense.getAdminEmail();
            emailStr=emailStr.replace("，",",");//中英文逗号都替换为英文逗号

            String invalidEmail="";
            StringBuilder newEmailStr=new StringBuilder();
            for(String email:emailStr.split(",")){
                email=StringUtils.trim(email);
                newEmailStr.append(","+email);
                if( !CommonUtils.validEmail(email) ){
                    invalidEmail=invalidEmail+","+email;
                }
            }

            if(!"".equals(invalidEmail)) {
                if(invalidEmail.startsWith(",")){
                    invalidEmail=invalidEmail.substring(1);
                }
                throw GatewayException.error("管理员邮箱不合法，非法邮箱："+invalidEmail);
            }

            systemLicense.setAdminEmail(StringUtils.trim(newEmailStr.substring(1)));
        }

        if(null==systemLicense.getSystemId()) {//新增，则检查名称相同的是否已经存在
            List<SystemLicenseExpire> list = systemLicenseExpireRepository.findBySystemName(systemLicense.getSystemName());
            if (null != list && list.size() > 0) {
                if (!(null != systemLicense.getSystemId() && list.get(0).getSystemId() == systemLicense.getSystemId())) {//更新
                    throw GatewayException.error("名称为：" + systemLicense.getSystemName() + "的系统已经存在，如需修改请选择编辑");
                }
            }
        }

        return systemLicenseExpireRepository.save(systemLicense);
    }

    /**
     * 查找实体
     *
     * @param id
     * @return
     */
    public SystemLicenseExpire findById(Integer id) {
        Optional<SystemLicenseExpire> optional = systemLicenseExpireRepository.findById(id);
        if (optional.isPresent()) {
            return optional.get();
        } else {
            return null;
        }
    }

    public void deleteById(Integer id) {
        systemLicenseExpireRepository.deleteById(id);
    }

    /**
     * 分页条件查询
     *
     * @param pageNo
     * @param pageSize
     * @param param
     * @return
     */
    public Page<SystemLicenseExpire> findPage(int pageNo, int pageSize, Map<String, Object> param) {
        Sort.Direction direction = Sort.Direction.DESC;
        String sort = "systemId";

        pageNo= PageUtil.initPageNo(pageNo);
        pageSize=PageUtil.initPageSize(pageSize);

        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, direction, sort);
        return systemLicenseExpireRepository.findAll(SpecificationUtil.buildSpecification(param, SystemLicenseExpire.class), pageable);
    }

    /**
     * 根据条件查询List
     */
    public List<SystemLicenseExpire> findList(Map<String, Object> param) {
        return systemLicenseExpireRepository.findAll(SpecificationUtil.buildSpecification(param, SystemLicenseExpire.class));
    }

    /**
     * 查询全部数据
     */
    public List<SystemLicenseExpire> findAll() {
        return systemLicenseExpireRepository.findAll();
    }


    @SneakyThrows
    @Transactional
    public ReportUploadContext<FortressNewMachineImportDto, String> upload(MultipartFile file, PlatformUserDto user) throws IOException {
        ReportUploadContext<FortressNewMachineImportDto, String> fortressMachineContext = ReportUploadContext.<FortressNewMachineImportDto, String>builder()
                .config(ReportFileConfigEnum.FORTRESS_NEW_MACHINE)
                .file(file)
                .build();
        ReportFileUtil.readSingleExcel(fortressMachineContext);
        AssertOverride.notEmpty(fortressMachineContext.getReadRes(), "sheet0不可为空");

//        ReportUploadContext<FortressAccountImportDto, String> fortressAccountContext = ReportUploadContext.<FortressAccountImportDto, String>builder()
//                .config(ReportFileConfigEnum.FORTRESS_ACCOUNT)
//                .file(file)
//                .check(this::checkCpuStandard)
//                .build();
//        ReportFileUtil.readSingleExcel(fortressAccountContext);
//        AssertOverride.notEmpty(fortressAccountContext.getReadRes(), "sheet1不可为空");

        List<IpSystemCode> ipSystemCodeList = systemMainService.queryIpSystemCode();
        Map<String,String> ipSystemCodeMap = ipSystemCodeList.stream().filter(e-> {
            return e!= null && StringUtils.isNotEmpty(e.getIp()) && StringUtils.isNotEmpty(e.getSystemCode());
        }).collect(Collectors.toMap(IpSystemCode::getIp, IpSystemCode::getSystemCode, (key1, key2) -> key2));
        List<SystemMain> systemMainList = systemMainService.queryAll();
        Map<String,String> systemNameMap = systemMainList.stream().collect(Collectors.toMap(SystemMain::getSystemClassNo, SystemMain::getOpName, (key1, key2) -> key2));
        LdapResponse<List<LdapEhrEmpDto>> ehrList = iFeignLdapService.getUserList(new LdapEhrEmpSearchDto());
        Map<String,LdapEhrEmpDto> ehrMap = ehrList.getData().stream().collect(Collectors.toMap(LdapEhrEmpDto::getBadge, Function.identity(), (key1, key2) -> key2));
        LdapResponse<List<LdapEhrDeptDto>> deptList = iFeignLdapService.getDepartmentList(new LdapEhrDeptSearchDto());
        Map<String,LdapEhrDeptDto> deptMap = deptList.getData().stream().map(e->{
            e.setDtitle(e.getDtitle().trim());
            return e;
        }).collect(Collectors.toMap(LdapEhrDeptDto::getDtitle, Function.identity(), (key1, key2) -> key2));
//        Map<String,FortressAccountImportDto> accountInfo = fortressAccountContext.getReadRes().stream().collect(Collectors.toMap(FortressAccountImportDto::getAccount, Function.identity(), (key1, key2) -> key2));
//        Map<String,List<FortressNewMachineImportDto>> machineInfo = fortressMachineContext.getReadRes().stream().collect(Collectors.groupingBy(FortressNewMachineImportDto::getAccount));
        Map<String,List<FortressNewMachineImportDto>> machineInfo = new HashMap<>();
        //改成按照账号导入，没有资产的为空
        List<FortressNew> fortressList = FortressNewMachineMapper.INSTANCE.dto2Do(fortressMachineContext.getReadRes());
        List<FortressNew> fortressListAdd = new ArrayList<>();
        fortressList.forEach(e -> {
            //ehr匹配上，且部门能找到的人
            if (ehrMap.keySet().contains(e.getAccount()) && !"admin".equals(e.getAccount()) && ehrMap.get(e.getAccount()).getDeptinfo() != null) {
                e.setNotOa(0);
                //对一个用户多个机器的数据进行处理
                fillMultipleMachine(e,machineInfo,ehrMap,ipSystemCodeMap,systemNameMap,fortressListAdd);
            } else if (StringUtils.isNotEmpty(e.getPosition())) {
                //ehr系统匹配不到的用户，用岗位里的值解析后再匹配到部门
                String[] position = e.getPosition().split("&");
                String deptName = position[0];
                String applyName = "";
                if (position.length > 1){
                    applyName = position[1];
                }
                LdapEhrDeptDto dept = deptMap.get(deptName.trim());
                if (dept == null){
                    e.setDepartmentOne("无法匹配人员");
                    fillSystemInfo(e,systemNameMap,ipSystemCodeMap);
                }
                //对一个用户多个机器的数据进行处理
//                List<FortressNewMachineImportDto> machineImportDtoList = machineInfo.get(e.getAccount());
//                if (CollectionUtil.isNotEmpty(machineImportDtoList) && machineImportDtoList.size() > 0){
//                    for (int i = 0; i < machineImportDtoList.size(); i++) {
//                        e.setMachine(machineImportDtoList.get(i).getMachine());
//                        FortressNew addFortress = new FortressNew();
//                        fillInfoByPosition(dept,e,systemNameMap,ipSystemCodeMap,applyName);
//                        BeanUtils.copyProperties(e, addFortress);
//                        addFortress.setMachine(machineImportDtoList.get(i).getMachine());
//                        fortressListAdd.add(addFortress);
//                    }
//                } else {
                    fillInfoByPosition(dept,e,systemNameMap,ipSystemCodeMap,applyName);
//                }
            } else {
                e.setDepartmentOne("无法匹配人员");
                //对一个用户多个机器的数据进行处理
                fillMultipleMachine(e,machineInfo,ehrMap,ipSystemCodeMap,systemNameMap,fortressListAdd);
            }
        });
//        fortressList = fortressList.stream().filter(e->{
//            return e.getNotOa() != 1;
//        }).collect(Collectors.toList());
        fortressList.addAll(fortressListAdd);
//        //异步处理
//        deleteAndSave(fortressList);
        fortressNewRepository.trancateTable();
        fortressNewRepository.saveAllAndFlush(fortressList);
        logger.info("fortress处理条数为"+fortressList.size());
        return fortressMachineContext;
    }

    private void fillMultipleMachine(FortressNew e, Map<String, List<FortressNewMachineImportDto>> machineInfo, Map<String, LdapEhrEmpDto> ehrMap, Map<String, String> ipSystemCodeMap, Map<String, String> systemNameMap, List<FortressNew> fortressListAdd) {
//        List<FortressNewMachineImportDto> machineImportDtoList = machineInfo.get(e.getAccount());
//        if (CollectionUtil.isNotEmpty(machineImportDtoList) && machineImportDtoList.size() > 0){
//            for (int i = 0; i < machineImportDtoList.size(); i++) {
//                e.setMachine(machineImportDtoList.get(i).getMachine());
//                FortressNew addFortress = new FortressNew();
//                fillFortressInfo(e,ehrMap,ipSystemCodeMap,systemNameMap);
//                BeanUtils.copyProperties(e, addFortress);
//                addFortress.setMachine(machineImportDtoList.get(i).getMachine());
//                fortressListAdd.add(addFortress);
//            }
//        } else {
            fillFortressInfo(e,ehrMap,ipSystemCodeMap,systemNameMap);
//        }
    }

    private void fillInfoByPosition(LdapEhrDeptDto dept, FortressNew e, Map<String, String> systemNameMap, Map<String, String> ipSystemCodeMap, String applyName) {
        if (StringUtils.isEmpty(e.getDepartmentOne())){
            String deparmentOneName = dept.getDepgrade().equals("一级部门") ? dept.getDtitle() : dept.getAtitle();
            try{
                e.setDepartmentOne(deparmentOneName.replaceAll("/","-"));
                e.setDepartmentOneId(dept.getDepgrade().equals("一级部门") ? dept.getDepid() : dept.getAdminid());
                e.setDepartmentTwo(dept.getDtitle());
                e.setDepartmentTwoId(dept.getDepid());
                e.setCompany(dept.getComptitle());
            }catch (Exception exception ){
                logger.error("无法匹配部门信息"+e.getAccount()+"--");
                exception.printStackTrace();
                e.setDepartmentOne("无法匹配人员");
            }

        }
        fillSystemInfo(e,systemNameMap,ipSystemCodeMap);
        if (StringUtils.isNotEmpty(applyName)){
            e.setRemark(applyName+"申请");
        }

    }

    private FortressNew fillFortressInfo(FortressNew e, Map<String, LdapEhrEmpDto> ehrMap, Map<String, String> ipSystemCodeMap, Map<String, String> systemNameMap) {
        //                e.setStatus(accountInfo.get(e.getAccount()).getStatus());
        if (StringUtils.isEmpty(e.getDepartmentOne())){
            String deparmentOneName = ehrMap.get(e.getAccount()).getDeptinfo().getDepgrade().equals("一级部门") ? ehrMap.get(e.getAccount()).getDeptinfo().getDtitle() : ehrMap.get(e.getAccount()).getDeptinfo().getAtitle();
            try {
                e.setDepartmentOne(deparmentOneName.replaceAll("/","-"));
                e.setDepartmentOneId(ehrMap.get(e.getAccount()).getDeptinfo().getDepgrade().equals("一级部门") ? ehrMap.get(e.getAccount()).getDeptinfo().getDepid() : ehrMap.get(e.getAccount()).getDeptinfo().getAdminid());
                e.setDepartmentTwo(ehrMap.get(e.getAccount()).getDeptinfo().getDtitle());
                e.setDepartmentTwoId(ehrMap.get(e.getAccount()).getDeptinfo().getDepid());
                e.setOaStatus(ehrMap.get(e.getAccount()).getStatus());
            } catch (Exception exception ){
                logger.error("无法匹配部门信息"+e.getAccount()+"--");
                exception.printStackTrace();
                e.setDepartmentOne("无法匹配人员");
            }
            if (!OaHrmresourceStatusEnum.isAlive(ehrMap.get(e.getAccount()).getStatus())){
                e.setDepartmentOne("无法匹配人员");
            }
            e.setCompany(ehrMap.get(e.getAccount()).getDeptinfo().getComptitle());
        }
//                e.setName(ehrMap.get(e.getAccount()).getName());
//                e.setAccountValidityFrom(accountInfo.get(e.getAccount()).getAccountValidityFrom());
//                e.setAccountValidityEnd(accountInfo.get(e.getAccount()).getAccountValidityEnd());
        fillSystemInfo(e,systemNameMap,ipSystemCodeMap);
        return e;
    }

    private void fillSystemInfo(FortressNew e, Map<String, String> systemNameMap, Map<String, String> ipSystemCodeMap) {
        if (StringUtils.isNotBlank(e.getIp())){
            String ip = e.getIp().trim();
            e.setSystemCode(ipSystemCodeMap.get(ip));
            if(StringUtils.isNotBlank(e.getSystemCode())){
                e.setSystemName(systemNameMap.get(e.getSystemCode()));
            }
        }
    }

//    @Async
//    private void deleteAndSave(List<Fortress> fortressList) {
//
//    }

    private void checkCpuStandard(FortressAccountImportDto fortressAccountImportDto) {
    }

    private void checkCpuStandard(FortressNewMachineImportDto FortressNewMachineImportDto) {
    }

    @SneakyThrows
    public byte[] export(Fortress param) {
        List<FortressNew> datas = fortressNewRepository.findAllByStatusNot("禁用");
        for (FortressNew e :datas) {
            try {
                entityManager.detach(e);
            } catch (Exception exception) {
                logger.error("entityManager清除缓存error：", exception);
            }
            if("信息技术总部".equals(e.getDepartmentOne())){
                String departmentOne = e.getDepartmentTwo().replaceAll("/","-");
                e.setDepartmentOne(departmentOne);
                e.setOaStatus("");
            } else if (!"无法匹配人员".equals(e.getDepartmentOne())){
                e.setDepartmentOne(e.getCompany()+"-"+e.getDepartmentOne());
                e.setOaStatus("");
            } else {
                //除无法匹配人员部门有这列，其他都不显示这个数据
                e.setOaStatus(OaHrmresourceStatusEnum.fromCode(e.getOaStatus()));
            }
        }

        Map<String, List<FortressNew>> dataMap = datas.stream().filter(e->e != null && e.getDepartmentOne() != null).collect(Collectors.groupingBy(FortressNew::getDepartmentOne));
        List<String> sheetNames = dataMap.keySet().stream().collect(Collectors.toList());
        Collections.sort(sheetNames, Collections.reverseOrder());
        List<List<FortressNew>> dataList = new ArrayList<>();
        for (String name :sheetNames) {
            Collections.sort(dataMap.get(name), (s1, s2) -> s1.getAccount().compareTo(s2.getAccount()));
            dataList.add(dataMap.get(name));
        }
        return ReportFileUtil.exportMultiSheet(dataList,sheetNames,ReportFileConfigEnum.FORTRESS_NEW_EXPORT);
    }

    public Object search(Object paramsObj) {
        JSONObject objParmams = JSONObject.parseObject(JSONObject.toJSONString(paramsObj)).entrySet().stream()
                .filter(entry -> !entry.getValue().toString().isEmpty())
                .collect(JSONObject::new, (obj, entry) -> obj.put(entry.getKey(), entry.getValue()), JSONObject::putAll);

        if (StrUtil.isEmpty(objParmams.getString("orderByDirection"))) {
            objParmams.put("orderByDirection", "ASC");
        }
        if (StrUtil.isEmpty(objParmams.getString("orderByField"))) {
            objParmams.put("orderByField", "id");
        }
        if (StringUtils.isEmpty(objParmams.getString("status"))){
            objParmams.put("notStatus","禁用");
        }
        Sort sort = Sort.by(Sort.Direction.fromString(objParmams.getString("orderByDirection")), objParmams.getString("orderByField"));

        Pageable pageable = PageRequest.of(objParmams.getInteger("pageNo") - 1, objParmams.getInteger("pageSize"), sort);

        FortressNew paramSearchDto = JSONObject.parseObject(JSONObject.toJSONString(objParmams), FortressNew.class);
        Page<FortressNew> result = fortressNewRepository.searchByParam(pageable, paramSearchDto);
//        result.getContent().forEach(e -> {
//            if (e.getCmdbCpuStandard() != null) {
//                e.setPartNum(e.getCmdbCpuStandard().getPartNum());
//            }
//        });
        return result;

    }
}
